
#include <string.h>
#include "define.h"
//#include "uart.h"
//#include "timer.h"
#include "rfid.h"
#include "nfc_hal_transfer.h"
#include "nfc_hal_config.h"
#include "nfc_hal_debug.h"
#include "stdio.h"

#include "iso14443a.h"
#include "iso14443b.h"
#include "iso14443_4.h"
#include "felica.h"
#include "iso15693.h"
#include "mifare.h"
#include "card_emu.h"
#include "bit_define.h"
#include "sys_init.h"
#include "app_tmos.h"
#include "CH58x_common.h"
#include "HAL.h"
#include "al_card_manager.h"
extern uint8_t NFC_DEBUG_LOG;

u8  g_query_mode_felica = 0;
u8  g_query_mode_iso15693 = 0;
u8  reqc_cmd[8];
u32  felica_num = 0;

tag_info  g_tag_info;
TypeV_Info_t bTypeV_Info_t;
u8 iso15693_uid[8];
statistics_t  g_statistics;
u8  g_statistic_refreshed;

u8 g_auto_read_write = 0;
u8 g_auto_read_typeB_id = 0;

//single attrib
u8 prama_ATQB[16];
u8 prama_rate;  //=pcmd[2];

U8 Test_Block_Init_Data[4]  =
{
        0x55, 0x00, 0x00, 0x00
};

U8 Test_Add_Sub_Step[4] =
{
        0x01, 0x00, 0x00, 0x00
};


//hal_nfc_regval_t COS_typeA_configs[] =
//{
//    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
//    {0, 0x02, 0x00},  //IRQ同向
//    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
//    {0, 0x08, 0x00},  //清除Mifare加密状态
//    {1, 0x11, 0x3D},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
//    {1, 0x12, 0x00},  //定义发送数据的帧结构
//    {1, 0x13, 0x00},  //定义接收数据的帧结构
//    {1, 0x15, 0x40},  //输出调制信号类型，bit6置1是OOK(A/V卡)，置0是ASK(B/F卡)
//    {1, 0x17, 0x92},  //配置接收等待时间
////    {1, 0x19, 0x2d},
//    {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
//    {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
//    {2, 0x28, 0xF0},  //发射场强调整
//    {4, 0x35, 0xe0},  //增益配置
//    {4, 0x36, 0x80},
//    {4, 0x3A, 0x01},  //低三位配置相位补偿，IQ翻转影响刷卡
//    {4, 0x3B, 0x6D},  //bit6置1，EMV认证用；bit6置0，正常模式用；bit5:3 噪声信号解调比，EMV认证测灵敏度时建议置101/110/111
//    {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
//    {6, 0x33, 0x10},  //bit5置1，ARC才会调整
//    {6, 0x3F, 0x70},  //bit6:4 A波下降沿调整
//    {7, 0x31, 0x22},  //LPF增益控制位，严重影响刷卡
//    {7, 0x32, 0x6A},  //接收内部Rtune调整
//    {7, 0x38, 0x0E},  //bit0=0关闭调制深度自适应功能
//    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
//    {7, 0x3E, 0x80},  //相位校准自动补偿bit7=1；手动补偿bit7=0
//    {8, 0x34, 0x69},  //ARC使能
//    {8, 0x39, 0xC8},  //多卡冲突调整
//    {10, 0x31, 0x30},  //TA上升沿步长
//    {10, 0x32, 0x0f},  //TA上升沿步数
//    {10, 0x33, 0x30},  //TA下降沿步长
//    {10, 0x34, 0xff},  //TA下降沿步数
//
//
//
//};
//
//hal_nfc_regval_t COS_typeB_configs[] =
//{
//    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
//    {0, 0x02, 0x00},  //IRQ同向
//    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
//    {0, 0x08, 0x00},
//    {0, 0x0D, 0x00},  //低三位只影响B卡且只能配置000；A卡无法修政
//    {1, 0x11, 0x3F},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
//    {1, 0x12, 0x83},  //定义发送数据的帧结构
//    {1, 0x13, 0x83},  //定义接收数据的帧结构
//    {1, 0x15, 0x00},  //输出调制信号类型，置1是OOK(A/V；置0是ASK(B/F)
//    {1, 0x17, 0x92},  //接收等待时间
////    {1, 0x19, 0x2d},
//    {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
//    {1, 0x1E, 0x03},  //B卡专用，SOF与EGT定义，新方案这一位有改动要配置成03
//    {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
//    {2, 0x28, 0xF0},  //P管发射场强调整
//    {2, 0x29, 0x32},  //P管MOD信号调整，改变调制深度
//    {4, 0x35, 0xE0},  //增益配置
//    {4, 0x36, 0x80},
//    {4, 0x3A, 0x04},  //低三位配置相位补偿，IQ翻转影响刷卡
//    {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
////    {6, 0x33, 0x10},  //B里面P6 0x33与P7 0X38开一个即可
//    {7, 0x31, 0x21},  //LPF增益控制位，严重影响刷卡
//    {7, 0x32, 0x68},  //接收内部Rtune调整
//    {7, 0x38, 0x1e},  //bit0调制深度自适应使能，若不使能，则配第六页33=10
//    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
//    {7, 0x3E, 0x80},  //相位校准补偿值使能
//    {8, 0x34, 0x69},  //ARC使能
//    {10, 0x35, 0x21},  //TB上升沿步长
//    {10, 0x36, 0xff},  //TB上升沿步数
//    {10, 0x38, 0x1D},  //TB下降沿步长
//    {10, 0x39, 0xff},  //TB下降沿步数
//};
//
//hal_nfc_regval_t typeF_configs[] =
//{
//    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
//    {0, 0x02, 0x00},
//    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
//    {1, 0x11, 0x3C},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
//    {1, 0x12, 0x92},  //定义发送数据的帧结构
//    {1, 0x13, 0x92},  //定义接收数据的帧结构
//    {1, 0x15, 0x00},  //输出调制信号类型，置1是OOK(A/V；置0是ASK(B/F)
//    {1, 0x17, 0x98},  //配置接收等待时间
////    {1, 0x19, 0x2d},
//    {1, 0x1D, 0x43},  //高通滤波器带宽设置
//    {2, 0x28, 0xf0},  //P管发射场强调整
//    {2, 0x29, 0x32},  //P管MOD信号调整，改变调制深度大小
//    {4, 0x33, 0x79},  //接收开始后AGC屏蔽时间设置，Felica与15693有影响
//    {4, 0x34, 0x7E},  //AGC调整后等待时间设置，Felica与15693有影响
//    {4, 0x35, 0xF0},  //增益设置
//    {4, 0x36, 0x80},
//    {4, 0x3A, 0x04},  //低三位配置相位补偿，IQ翻转影响刷卡
//    {5, 0x34, 0x50},  //Felica建议Bypass AWC功能
//    {6, 0x33, 0x10},  //bit5置1，ARC才会调整
//    {7, 0x32, 0x68},  //接收内部Rtune调整
//    {7, 0x38, 0x0E},  //bit0=0关闭调制深度自适应功能
//    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
//    {7, 0x3E, 0x80},  //相位校准补偿值使能
//    {8, 0x34, 0x69},  //ARC使能
//    {8, 0x3C, 0x00},  //关闭B卡防冲突功能bit0置0，Felica工作时需要关闭B卡防冲突功能
////    {10, 0x35, 0x21},  //TB上升沿步长
////    {10, 0x36, 0xff},  //TB上升沿步数
////    {10, 0x38, 0x1D},  //TB下降沿步长
////    {10, 0x39, 0xff},  //TB下降沿步数
//
//};
//
//hal_nfc_regval_t typeV_configs[] =
//{
//    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
//    {0, 0x02, 0x00},
//    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
//    {1, 0x11, 0x3F},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
//    {1, 0x12, 0x80},  //定义发送数据的帧结构
//    {1, 0x13, 0x80},  //定义接收数据的帧结构
//    {1, 0x15, 0x40},  //输出调制信号类型，置1是OOK(A/V；置0是ASK(B/F)
//    {1, 0x17, 0x98},  //配置接收等待时间
////    {1, 0x19, 0x2d},
//    {1, 0x1D, 0x64},  //高通滤波器带宽设置
//    {2, 0x28, 0xf0},  //P管发射场强调整
//    {4, 0x33, 0xD1},  //接收开始后AGC屏蔽时间设置，Felica与15693有影响
//    {4, 0x34, 0x7E},  //AGC调整后等待时间设置，Felica与15693有影响
//    {4, 0x35, 0xF0},  //增益设置
//    {4, 0x36, 0x80},
//    {4, 0x3A, 0x04},  //低三位配置相位补偿，IQ翻转影响刷卡
//    {5, 0x34, 0x50},  //15693建议Bypass AWC功能
//    {6, 0x33, 0x10},  //bit5置1，ARC才会调整
//    {7, 0x31, 0x21},  //LPF增益控制位，严重影响刷卡，下版配置为02
//    {7, 0x32, 0x68},  //接收内部Rtune调整
//    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
//    {7, 0x3E, 0x80},  //相位校准补偿值使能
//    {8, 0x31, 0xC1},  //15693功能使能
//    {8, 0x34, 0x69},  //ARC使能
////    {10, 0x31, 0x30},  //TA上升沿步长
////    {10, 0x32, 0x0f},  //TA上升沿步数
////    {10, 0x33, 0x30},  //TA下降沿步长
////    {10, 0x34, 0xff},  //TA下降沿步数
//};


lpcd_config_t g_lpcd_config=
{
        .g_lpcd_config_test_start =FALSE,
        .delta                    =0,
        .t_inactivity_ms          =0,
        .skip_times               =0,
        .t_detect_us              =0,
        .detect_way               =1,
        .card_to_enter            =FALSE,
};


polling_15693_s g_15693_polling_conf=
{
        .blocknum                   =0x00,
        .blocksize                  =0x00,
        .flag                       =0x22,


};

static WORK_MODE_DEF work_mode = MODE_PCD_ONLY;
extern void make_packet(u8 cmd, u8 *buf, u8 len);
void com_halt_a(void);
uint8_t com_mf1_read(u8 *pcmd);
uint8_t com_mf1_write(u8 *pcmd);
void com_mf0_read(u8 *pcmd);
void com_mf0_write(u8 *pcmd);

void com_halt_b(u8 *pcmd);
void com_sr176_read(u8 *pcmd);
void com_sr176_write(u8 *pcmd);
void com_select_sr(void);
void com_protect_sr176(u8 *pcmd);
void com_complect_sr(void);
void com_get_idcard_num(void);
void auto_write_read_after_reqa(void);
void com_typea_rats(u8 *pcmd);
void com_exchange(u8 * pcmd);
void com_multi_exchange_test(u8 *pcmd);
void InitBlock(unsigned char addr,unsigned char *value);
void com_value_add(u8 * pcmd);
void com_value_decrease(u8 * pcmd);
void com_mf1_step_auth(u8 * pcmd);
void com_mf1_step_read(u8 *pcmd);
void com_mf1_step_write(u8 *pcmd);
void com_stay_quiet(u8 *pcmd);
void com_reset_to_ready(u8 *pcmd);
void com_select(u8 *pcmd);
void com_get_block_status(u8 *pcmd);
void com_read_single_block(u8 *pcmd);
void com_write_single_block(u8 *pcmd);
void com_get_sys_info(u8 *pcmd);
void com_lock_block(u8 *pcmd);
void com_read_multiple_block(u8 *pcmd);
void com_write_multiple_block(u8 *pcmd);
void com_write_afi(u8 * pcmd);
void com_lock_afi(u8 *pcmd);
void com_write_dsfid(u8 * pcmd);
void com_lock_dsfid(u8 *pcmd);
void com_transfer(u8* pcmd);
void init_rfid()
{
    memset(&g_tag_info, 0, sizeof(g_tag_info));
    memset(&g_statistics, 0, sizeof(g_statistics));
    g_tag_info.block.num = 4;
    g_tag_info.uncoded_key_is_a = 1;
}

static const hal_nfc_regval_t COS_typeA_configs[] =
{
        {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
        {0, 0x02, 0x00},  //IRQ同向
        {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
        {0, 0x08, 0x00},  //清除Mifare加密状态
        {1, 0x11, 0x3D},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
        {1, 0x12, 0x00},  //定义发送数据的帧结构
        {1, 0x13, 0x00},  //定义接收数据的帧结构
        {1, 0x15, 0x40},  //输出调制信号类型，bit6置1是OOK(A/V卡)，置0是ASK(B/F卡)
        {1, 0x17, 0x92},  //配置接收等待时间
        {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
        {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
        {2, 0x28, 0xF0},  //发射场强调整
        {4, 0x35, 0xe0},  //增益配置
        {4, 0x36, 0x80},
        {4, 0x3A, 0x01},  //低三位配置相位补偿，IQ翻转影响刷卡
        {4, 0x3B, 0x6D},  //bit6置1，EMV认证用；bit6置0，正常模式用；bit5:3 噪声信号解调比，EMV认证测灵敏度时建议置101/110/111
        {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
        {6, 0x33, 0x10},    //bit5置1，ARC才会调整
        {6, 0x3F, 0x70},  //bit6:4 A波下降沿调整
        {7, 0x31, 0x20},  //LPF增益控制位，严重影响刷卡
        {7, 0x32, 0x68},  //接收内部Rtune调整
        {7, 0x38, 0x0E},  //bit0=0关闭调制深度自适应功能
        {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
        {7, 0x3E, 0x80},  //相位校准自动补偿bit7=1；手动补偿bit7=0
        {8, 0x34, 0x69},  //ARC使能
        {8, 0x39, 0xC6},  //多卡冲突调整
        {10, 0x31, 0x30},  //TA上升沿步长
        {10, 0x32, 0x0f},  //TA上升沿步数
        {10, 0x33, 0x30},  //TA下降沿步长
        {10, 0x34, 0xff},  //TA下降沿步数
};

static const hal_nfc_regval_t COS_typeB_configs[] =
{
        {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
        {0, 0x02, 0x00},  //IRQ同向
        {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
        {0, 0x08, 0x00},
        {0, 0x0D, 0x00},  //低三位只影响B卡且只能配置000；A卡无法修政
        {1, 0x11, 0x3F},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
        {1, 0x12, 0x83},  //定义发送数据的帧结构
        {1, 0x13, 0x83},  //定义接收数据的帧结构
        {1, 0x15, 0x00},  //输出调制信号类型，置1是OOK(A/V；置0是ASK(B/F)
        {1, 0x17, 0x92},  //接收等待时间
        {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
        {1, 0x1E, 0x03},  //B卡专用，SOF与EGT定义，新方案这一位有改动要配置成03
        {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
        {2, 0x28, 0xF0},  //P管发射场强调整
        {2, 0x29, 0x32},  //P管MOD信号调整，改变调制深度
        {4, 0x35, 0xE0},  //增益配置
        {4, 0x36, 0x80},
        {4, 0x3A, 0x01},  //低三位配置相位补偿，IQ翻转影响刷卡
        {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
        //    {6, 0x33, 0x10},  //B里面P6 0x33与P7 0X38开一个即可
        {7, 0x31, 0x21},  //LPF增益控制位，严重影响刷卡
        {7, 0x32, 0x68},  //接收内部Rtune调整
        {7, 0x38, 0x1F},  //bit0调制深度自适应使能，若不使能，则配第六页33=10
        {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
        {7, 0x3E, 0x80},  //相位校准补偿值使能
        {8, 0x34, 0x69},  //ARC使能
        {10, 0x35, 0x21},  //TB上升沿步长
        {10, 0x36, 0xff},  //TB上升沿步数
        {10, 0x38, 0x1D},  //TB下降沿步长
        {10, 0x39, 0xff},  //TB下降沿步数
};


//void rfid_set_protocol(char protocol) {
//    switch (protocol) {
//    case 'A':
//        hal_nfc_config(COS_typeA_configs, sizeof(COS_typeA_configs)/sizeof(hal_nfc_regval_t));
//        break;
//    case 'B':
//        hal_nfc_config(COS_typeB_configs, sizeof(COS_typeB_configs)/sizeof(hal_nfc_regval_t));
//        break;
//    case 'F':
//        hal_nfc_config(typeF_configs, sizeof(typeF_configs)/sizeof(hal_nfc_regval_t));
//        break;
//    case 'V':
//        hal_nfc_config( typeV_configs, sizeof(typeV_configs)/sizeof(hal_nfc_regval_t));
//        break;
//    default:
//        break;
//    }
//}

void card_operation(u8 *pcmd)
{
    switch(pcmd[0])
    {
    //    case COM_PKT_CMD_INIT_TYPEA:
    //        hal_nfc_config(COS_typeA_configs, sizeof(COS_typeA_configs)/sizeof(hal_nfc_regval_t));
    //        printf("typeA OK\n");
    //        break;
    //    case COM_PKT_CMD_INIT_TYPEB:
    //        hal_nfc_config(COS_typeB_configs, sizeof(COS_typeB_configs)/sizeof(hal_nfc_regval_t));
    //        printf("typeB OK\n");
    //        break;
    //    //Type A
    //    case COM_PKT_CMD_REQA:
    //
    //        pcd_set_rate('1', 'A');
    //        com_reqa(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_HALT:
    //        com_halt_a();
    //        break;
    //
    //    case COM_PKT_CMD_TYPEA_MF1_READ:
    //        com_mf1_read(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_WRITE:
    //        com_mf1_write(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_VALUE_BLOCK_OP:
    //        com_mf1_value_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_WALLET_INIT:
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_WALLET_READ:
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_WALLET_INCREMENT:
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_WALLET_DECREMENT:
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF0_READ:
    //        com_mf0_read(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF0_WRITE:
    //        com_mf0_write(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_RATS:
    //        com_typea_rats(pcmd);
    //        break;
    //    //Type B
    //    case COM_PKT_CMD_REQB:
    //        pcd_set_rate('1', 'B');
    //        com_reqb(pcmd);
    //
    //        break;
    //    case COM_PKT_CMD_TYPEB_ATTRIB:
    //        //pcd_pps_rate_b();
    //        com_typeb_attrib();
    //        break;
    //    case COM_PKT_CMD_TYPEB_HALT:
    //        com_halt_b(pcmd);
    //        break;
    //    case COM_PKT_CMD_SELECT_SR:
    //        com_select_sr();
    //        break;
    //    case COM_PKT_CMD_TYPEB_SR176_READ:
    //        com_sr176_read(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEB_SR176_WRITE:
    //        com_sr176_write(pcmd);
    //        break;
    //    case COM_PKT_CMD_PROTECT_SR176:
    //        com_protect_sr176(pcmd);
    //        break;
    //    case COM_PKT_CMD_COMPLECT_SR176:
    //        com_complect_sr();
    //        break;
    //    case COM_PKT_CMD_TYPEB_UID:
    //        com_get_idcard_num();
    //        break;
    //    //ISO14443_4_HalfDuplexExchange
    //    case COM_PKT_CMD_EXCHANGE:
    //        com_exchange(pcmd);
    //        break;
    //    case COM_PKT_CMD_MULTI_EXCHANGE_TEST:
    //        com_multi_exchange_test(pcmd);
    //        break;
    //    case COM_PKT_CMD_DESELECT:
    //        iso14443_4_deselect(0);
    //        break;
    //    case COM_PKT_CMD_STATISTICS:
    //        led_fail_off();
    //        memset(&g_statistics, 0, sizeof(g_statistics));
    //        printf("statistics cleared");
    //        break;
    //
    //    case COM_PKT_CMD_mf1_block_init:
    //    case COM_PKT_CMD_mf1_block_value_add:
    //        com_value_add(pcmd);
    //        break;
    //    case COM_PKT_CMD_mf1_block_value_decrease:
    //        com_value_decrease(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_STEP_AUTH:
    //        com_mf1_step_auth(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_STEP_READ:
    //        com_mf1_step_read(pcmd);
    //        break;
    //    case COM_PKT_CMD_TYPEA_MF1_STEP_WRITE:
    //        com_mf1_step_write(pcmd);
    //        break;
    //    case COM_PKT_CMD_FELICA_CONFIG:
    //        hal_nfc_config(typeF_configs, sizeof(typeF_configs)/sizeof(hal_nfc_regval_t));
    //        printf("typeF OK\n");
    //        break;
    //    case COM_PKT_CMD_TYPEC_FELICA_REQC:
    //        if(pcmd[1] == 0x01)
    //        {
    //            printf("212k\n");
    //            pcd_set_rate('2', 'F');
    //        }
    //        else if(pcmd[1] == 0x02)
    //        {
    //            printf("424k\n");
    //            pcd_set_rate('4', 'F');
    //        }
    //        com_reqc(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_CONFIG:
    //        hal_nfc_config( typeV_configs, sizeof(typeV_configs)/sizeof(hal_nfc_regval_t));
    //        printf("typeV OK\n");
    //        break;
    //    case COM_PKT_CMD_ISO15693_INVENTORY:
    //        com_inventory(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_STAY_QUIET:
    //        com_stay_quiet(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_RESET_TO_READY:
    //        com_reset_to_ready(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_SELECT:
    //        com_select(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_GET_STATUS:
    //        com_get_block_status(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_GET_SYSTEM:
    //        com_get_sys_info(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_READ_SINGLE:
    //        com_read_single_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_WRITE_SINGLE:
    //        com_write_single_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_LOCK_BLOCK:
    //        com_lock_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_READ_MULTIPLE:
    //        com_read_multiple_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_WRITE_MULTIPLE:
    //        com_write_multiple_block(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_WRITE_AFI:
    //        com_write_afi(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_LOCK_AFI:
    //        com_lock_afi(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_WRITE_DSFID:
    //        com_write_dsfid(pcmd);
    //        break;
    //    case COM_PKT_CMD_ISO15693_LOCK_DSFID:
    //        com_lock_dsfid(pcmd);
    //        break;
    //    case COM_PKT_CMD_TRANSCEIVE:
    //        com_transfer(pcmd);
    //        break;
    default:
        break;
    }

}

char com_reqa(u8 *pcmd)
{
    int  status;
    u8  sak;
    u8  buf[10];
    //typeA寻卡
    g_statistics.reqa_cnt++;
    g_statistics.m1_cnt++;
    g_statistic_refreshed=TRUE;

    pcd_default_info();

    status = pcd_request(pcmd[1], g_tag_info.tag_type_bytes);

    printf("pcd_request\n");
    //一次防冲突及选卡
    if ((status == MI_OK) || (status == MI_COLLERR))
    {
        g_tag_info.uid_length = UID_4;
        make_packet(COM_PKT_CMD_CARD_TYPE, g_tag_info.tag_type_bytes, sizeof(g_tag_info.tag_type_bytes));
        //g_tag_info.tag_type = check_tag_type(g_tag_info.tag_type_bytes);
        status = pcd_cascaded_anticoll(PICC_ANTICOLL1, 0, &g_tag_info.serial_num[0]);
        if (status == MI_OK)
        {
            status = pcd_cascaded_select(PICC_ANTICOLL1, &g_tag_info.serial_num[0], &sak);
        }
    }
    //二次防冲突及选卡
    if(status == MI_OK && (sak & BIT2))
    {
        g_tag_info.uid_length = UID_7;
        status = pcd_cascaded_anticoll(PICC_ANTICOLL2, 0, &g_tag_info.serial_num[4]);
        if(status == MI_OK)
        {
            status = pcd_cascaded_select(PICC_ANTICOLL2, &g_tag_info.serial_num[4], &sak);
        }
    }
    //回复UID
    if (status == MI_OK)
    {
        buf[0] = g_tag_info.uid_length;
        memcpy(buf+1, (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0]:&g_tag_info.serial_num[1]), g_tag_info.uid_length);
        //        sys_delay_ms(50);
        //       // make_packet(COM_PKT_CMD_REQA, buf, g_tag_info.uid_length + 1);
        //        sys_delay_ms(50);
    }

    if(status == MI_OK)
    {
        printf("reqa_ok\n");
    }
    else
    {
        g_statistics.reqa_fail++;
        g_statistics.m1_fail++;
        printf("reqa_fail\n");
    }

    return status;
}

void com_halt_a()
{
    u8  status;

    status = pcd_hlta();
    make_packet(COM_PKT_CMD_TYPEA_HALT, &status, sizeof(status));
}

uint8_t com_mf1_read(u8 *pcmd)
{
    u8 status;
    u8 block;
    u8 is_a;
    u8  buf[17];
    u8 pkey[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

    block = pcmd[0];
    is_a = pcmd[1];
    g_statistics.m1_cnt++;
    g_statistic_refreshed=TRUE;

    status = pcd_auth_state(PICC_AUTHENT1A, block, pcmd+2, pkey);

    //    status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, \
    //                            (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0] : (g_tag_info.uid_length == UID_7 ? &g_tag_info.serial_num[4] : &g_tag_info.serial_num[7])), &pcmd[3]);

    if (status == MI_OK)
    {
        status = pcd_read(block, buf + 1);
    }
    if (status == MI_OK)
    {
        buf[0] = block;
        dk_log_hex("buf", buf, 17);
        //make_packet(COM_PKT_CMD_TYPEA_MF1_READ, buf, sizeof(buf));
    }
    if(status != MI_OK)
    {
        g_statistics.m1_fail++;
    }
    return status;
}

uint8_t com_mf1_write(u8 *pcmd)
{
    u8  status;
    u8  block;
    u8  is_a;

    block = pcmd[1];
    is_a = pcmd[2];
    g_statistics.m1_cnt++;
    g_statistic_refreshed=TRUE;
    status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, \
            (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0] : (g_tag_info.uid_length == UID_7 ? &g_tag_info.serial_num[4] : &g_tag_info.serial_num[7])), &pcmd[3]);

    if (status == MI_OK)
    {
        status = pcd_write(block, &pcmd[9]);
    }
    if(status != MI_OK)
    {
        g_statistics.m1_fail++;
    }
    make_packet(COM_PKT_CMD_TYPEA_MF1_WRITE, &status, sizeof(status));
    return status;
}

void com_mf0_read(u8 *pcmd)
{
    u8  status;
    u8  block;
    u8  buf[17];

    block = pcmd[1];

    status = pcd_read(block, buf + 1);

    if (status == MI_OK)
    {
        buf[0] = block;
        make_packet(COM_PKT_CMD_TYPEA_MF0_READ, buf, sizeof(buf));
    }
}

void com_mf0_write(u8 *pcmd)
{
    u8  status;
    u8  block;

    block = pcmd[1];

    status = pcd_write_ultralight(block, &pcmd[2]);

    make_packet(COM_PKT_CMD_TYPEA_MF0_WRITE, &status, sizeof(status));
}

char polling_reqb(u8 *pcmd)
{
    int  status;
    u8  i;
    u8  cnt;
    u8  ATQB[16];
    u8  req_code;
    u8  rate;

    g_statistics.reqb_cnt++;
    g_statistic_refreshed=TRUE;

    req_code = pcmd[1];
    cnt = 1;

    while(cnt--)
    {
        status = pcd_request_b(req_code, 0, 0, ATQB);
        memcpy(prama_ATQB,ATQB,16);

        if(status == MI_COLLERR)
        {
            printf("COLL_DET_B\n");
            if((status = pcd_request_b(req_code, 0, 2, ATQB)) != MI_OK)
            {
                //Timeslot approach
                for (i = 1; i < 4; i++)
                {
                    if((status = pcd_slot_marker(i, ATQB)) == MI_OK)
                    {
                        break;
                    }
                }
                if (status == MI_OK)
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }
        else if (status == MI_OK)
        {
            break;
        }
    }

    if (status == MI_OK)
    {
        rate = pcmd[2];
        prama_rate=pcmd[2];

        if(rate == 1 || rate == 2 || rate == 4 || rate == 8)
        {
            status = pcd_pps_rate_b(PICC_CID, ATQB, rate);
        }
        else
        {
            status = pcd_attri_b(&ATQB[1], 0, ATQB[10]&0x0f, PICC_CID, ATQB);
        }


        if (status == MI_OK)
        {
            ATQB[0] = 0x50;
            make_packet(COM_PKT_CMD_REQB, ATQB, 12);
        }
    }

    if(status == MI_OK)
    {
        if (g_auto_read_typeB_id==1)
        {
            u8  id[10];
            if (get_idcard_num(id) == MI_OK)
            {
                sys_delay_ms(10);
                make_packet(COM_PKT_CMD_TYPEB_UID, id, 10);
            }
        }
        else
        {
        }
    }
    else
    {
        g_statistics.reqb_fail++;
        printf("reqa_fail\n");
    }

    return status;
}


char com_reqb(u8 *pcmd)
{
    int  status;
    u8  i;
    u8  cnt;
    u8  ATQB[16];
    u8  req_code;
    u8  rate;

    g_statistics.reqb_cnt++;
    g_statistic_refreshed=TRUE;

    req_code = pcmd[1];
    cnt = 1;

    while(cnt--)
    {
        status = pcd_request_b(req_code, 0, 0, ATQB);
        memcpy(prama_ATQB,ATQB,16);

        if(status == MI_COLLERR)
        {
            if((status = pcd_request_b(req_code, 0, 2, ATQB)) != MI_OK)
            {
                //Timeslot approach
                for (i = 1; i < 4; i++)
                {
                    if((status = pcd_slot_marker(i, ATQB)) == MI_OK)
                    {
                        break;
                    }
                }
                if (status == MI_OK)
                {
                    break;
                }
            }
            else
            {
                break;
            }
        }
        else if (status == MI_OK)
        {
            break;
        }
    }

    if (status == MI_OK)
    {
        rate = pcmd[2];
        prama_rate=pcmd[2];

        if(rate == 1 || rate == 2 || rate == 4 || rate == 8)
        {
            status = pcd_pps_rate_b(PICC_CID, ATQB, rate);
        }
        if (status == MI_OK)
        {
            ATQB[0] = 0x50;
            make_packet(COM_PKT_CMD_REQB, ATQB, 12);
        }
    }

    if(status == MI_OK)
    {
        if (g_auto_read_typeB_id==1)
        {
            u8  id[10];
            if (get_idcard_num(id) == MI_OK)
            {
                sys_delay_ms(10);
                make_packet(COM_PKT_CMD_TYPEB_UID, id, 10);
            }
        }
    }
    else
    {
        g_statistics.reqb_fail++;
        printf("reqa_fail\n");
    }

    return status;
}

void com_halt_b(u8 *pcmd)
{
    u8  status;
    //    pcmd = pcmd;

    status = pcd_halt_b(pcmd + 1);// 4 bytes uid

    make_packet(COM_PKT_CMD_TYPEB_HALT, &status, sizeof(status));
}

void com_get_idcard_num()
{
    u8  id[10];
    char  status;

    status = get_idcard_num(id);
    if (status == MI_OK)
    {
        make_packet(COM_PKT_CMD_TYPEB_UID, id, 10);
    }
    else
    {
        make_packet(COM_PKT_CMD_STATISTICS, (u8*)&g_statistics, sizeof(g_statistics));
    }
}

void com_select_sr()
{
    char  status;
    u8  chip_id;

    status = select_sr(&chip_id);
    if (status == MI_OK)
    {
        make_packet(COM_PKT_CMD_SELECT_SR, &chip_id, sizeof(chip_id));
    }
}

void com_sr176_read(u8 *pcmd)
{
    char  status;
    u8  buf[3];

    status = read_sr176(pcmd[1], buf + 1);

    if (status == MI_OK)
    {
        buf[0] = pcmd[1];
        make_packet(COM_PKT_CMD_TYPEB_SR176_READ, buf, sizeof(buf));
    }
}
void com_sr176_write(u8 *pcmd)
{
    uint8_t  status;

    status = write_sr176(pcmd[1], &pcmd[2]);

    if (status == MI_OK)
    {
        make_packet(COM_PKT_CMD_TYPEB_SR176_WRITE, &status, sizeof(status));
    }
}

void com_protect_sr176(u8 *pcmd)
{
    uint8_t  status;
    u8  block;

    block = pcmd[1];
    status = protect_sr176(block);
    if (status == MI_OK)
    {
        make_packet(COM_PKT_CMD_PROTECT_SR176, &status, sizeof(status));
    }
}
void com_complect_sr()
{
    u8  status;
    status = completion_sr();

    make_packet(COM_PKT_CMD_COMPLECT_SR176, &status, sizeof(status));
}

void statistic_print()
{
    statistics_t statistics_tmp;

    if (g_statistic_refreshed == TRUE)
    {
        sys_delay_ms(20);
        memcpy(&statistics_tmp, &g_statistics, sizeof(g_statistics));

        statistics_tmp.reqa_cnt = htonl(statistics_tmp.reqa_cnt);
        statistics_tmp.reqa_fail = htonl(statistics_tmp.reqa_fail);
        statistics_tmp.cosa_fail = htonl(statistics_tmp.cosa_fail);
        statistics_tmp.cosa_cnt = htonl(statistics_tmp.cosa_cnt);

        statistics_tmp.reqb_cnt = htonl(statistics_tmp.reqb_cnt);
        statistics_tmp.reqb_fail = htonl(statistics_tmp.reqb_fail);
        statistics_tmp.cosb_fail = htonl(statistics_tmp.cosb_fail);
        statistics_tmp.cosb_cnt = htonl(statistics_tmp.cosb_cnt);

        statistics_tmp.felica_cnt = htonl(statistics_tmp.felica_cnt);
        statistics_tmp.felica_fail = htonl(statistics_tmp.felica_fail);

        statistics_tmp.inv_cnt = htonl(statistics_tmp.inv_cnt);
        statistics_tmp.inv_fail = htonl(statistics_tmp.inv_fail);
        statistics_tmp.inv_check_fail = htonl(statistics_tmp.inv_check_fail);
        statistics_tmp.inv_write_fail = htonl(statistics_tmp.inv_write_fail);

        statistics_tmp.m1_cnt = htonl(statistics_tmp.m1_cnt);
        statistics_tmp.m1_fail = htonl(statistics_tmp.m1_fail);

        statistics_tmp.authenticate_fail = htonl(statistics_tmp.authenticate_fail);

        statistics_tmp.lpcd_cnt = htonl(statistics_tmp.lpcd_cnt);
        statistics_tmp.lpcd_fail = htonl(statistics_tmp.lpcd_fail);

        make_packet(COM_PKT_CMD_STATISTICS, (u8*)&statistics_tmp, sizeof(statistics_tmp));
        g_statistic_refreshed = FALSE;
    }
}

void statistic_cleared()
{
    memset(&g_statistics,0,sizeof(g_statistics));

}

void com_typea_rats(u8 * pcmd)
{
    char  status;
    u8  CID = 0;
    u8  ats[3];
    u8  rate;
    hal_nfc_transceive_t pi;

    status = pcd_rats_a(CID, ats);
    if(status == MI_OK)
    {
        if (pcmd[1] != 0)
        {
            rate = pcmd[1];
            status = pcd_pps_rate(&pi, ats, CID, rate);
        }
    }
    g_statistic_refreshed = TRUE;

}
void com_exchange(u8 * pcmd)
{
    u8  loop_buf[256];
    char  status;

    u16  tx_len;
    unsigned int rx_len;

    g_statistics.cosa_cnt++;  //mark
    g_statistics.cosb_cnt++;

    tx_len = pcmd[1];
    memcpy(loop_buf, pcmd + 2, tx_len);

    status = ISO14443_4_HalfDuplexExchange(&g_pcd_module_info, loop_buf, tx_len, loop_buf, &rx_len);

    if (status == MI_OK && rx_len < sizeof(loop_buf))
    {
        memmove(loop_buf+1, loop_buf, rx_len);
        loop_buf[0]=rx_len;
        //make_packet(COM_PKT_CMD_EXCHANGE, (u8*)&loop_buf, rx_len + 1);
    }
    if (status != MI_OK)
    {
        g_statistics.cosa_fail++; //mark
        g_statistics.cosb_fail++;
    }


    g_statistic_refreshed = TRUE;


}

u32  g_cos_loop_times = 0;
u8 g_cos_loop = FALSE;
u8  g_loop_buf[60];

void com_multi_exchange_test(u8 *pcmd)
{
    g_cos_loop=TRUE;

    g_cos_loop_times = (pcmd[1]<<24) + (pcmd[2]<<16) + (pcmd[3]<<8) + pcmd[4];
    if(g_cos_loop_times>0)
    {   //清空统计 mark
        statistic_cleared();
        g_statistic_refreshed = FALSE;
    }
    if(pcmd[1 + sizeof(u32)] + 1 <= sizeof(g_loop_buf))
    {
        g_cos_loop_times = (pcmd[1]<<24) + (pcmd[2]<<16) + (pcmd[3]<<8) + pcmd[4];
        g_loop_buf[0]= pcmd[sizeof(u32)];
        memcpy(g_loop_buf + 1, pcmd + 1 + sizeof(u32), pcmd[1 + sizeof(u32)] + 1);
    }
    else
    {
        printf("multi cos data > g_loop_buf\n");
    }
}

void com_value_add(u8 * pcmd)
{
    u8  status;
    u8  block;
    u8  is_a;

    block = pcmd[1];
    is_a = pcmd[2];

    status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0] : &g_tag_info.serial_num[4]), &pcmd[3]);

    status = pcd_valueblock_operation(PICC_INCREMENT,block,Test_Add_Sub_Step);
    if (status == MI_OK)
    {
        printf("com_value_add:ok\r\n");
    }
    else
    {
        printf("com_value_add:fail\r\n");
    }
}

void com_value_decrease(u8 * pcmd)
{
    u8  status;
    u8  block;
    u8   is_a;

    block = pcmd[1];
    is_a = pcmd[2];

    status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0] : &g_tag_info.serial_num[4]), &pcmd[3]);
    status = pcd_valueblock_operation(PICC_DECREMENT,block,Test_Add_Sub_Step);
    if (status == MI_OK)
    {
        printf("com_value_add:ok\r\n");
    }
    else
    {
        printf("com_value_add:fail\r\n");
    }
}

void com_mf1_value_block(u8 *pcmd)
{
    u8 status;
    u8 block;
    u8 is_a;

    block = pcmd[1];
    is_a = pcmd[2];

    if(g_tag_info.uid_length == UID_4)
    {
        status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, &g_tag_info.serial_num[0], &pcmd[3]);
    }
    else if(g_tag_info.uid_length == UID_7)
    {
        status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, &g_tag_info.serial_num[4], &pcmd[3]);
    }
    else if(g_tag_info.uid_length == UID_10)
    {
        status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, &g_tag_info.serial_num[7], &pcmd[3]);
    }

    if (status == MI_OK)
    {
        status = pcd_valueblock_operation(pcmd[13], block, &pcmd[9]);
        if (status == MI_OK)
        {
            status = pcd_valueblock_transfer(block);
        }
    }

}

void com_mf1_step_auth(u8 * pcmd)
{
    printf("AUTH:/r/n");
    u8  status;
    u8  block;
    u8  is_a;

    block = pcmd[1];
    is_a = pcmd[2];

    status = pcd_auth_state((is_a == TRUE ? PICC_AUTHENT1A : PICC_AUTHENT1B), block, (g_tag_info.uid_length == UID_4 ? &g_tag_info.serial_num[0] : &g_tag_info.serial_num[4]), &pcmd[3]);
    if(MI_OK!=status)
    {
        g_statistics.authenticate_fail++;
    }

}

void com_mf1_step_read(u8 *pcmd)
{
    u8  status;
    u8  block;

    u8  buf[17];

    block = pcmd[1];


    status = pcd_read(block, buf + 1);

    if (status == MI_OK)
    {
        buf[0] = block;
        make_packet(COM_PKT_CMD_TYPEA_MF1_READ, buf, sizeof(buf));
    }
}

void com_mf1_step_write(u8 *pcmd)
{
    u8 status;
    u8 block;


    block = pcmd[1];

    status = pcd_write(block, &pcmd[9]);

    make_packet(COM_PKT_CMD_TYPEA_MF1_WRITE, &status, sizeof(status));
}

u8 com_status_check(char status)
{
    switch(status)
    {
    //    case MI_NOTAGERR:
    //        return 0x01;
    //
    //    case MI_INTEGRITY_ERR:
    //        return 0x02;
    //
    //    case MI_COLLERR:
    //        return 0x04;
    //
    //    case PROTOCOL_ERR:
    //        return 0x08;
    //
    //    case MI_COM_ERR:
    //        return 0x10;

    default:
        return 0xFF;

    }
}

int com_reqc(u8 *pcmd)
{
    int status;
    u8 err;
    u8  rsp[18];
    u8  node_code_list[2] = {0x00, 0x00};
    u8  node_key_version_list[2];
    u8  node_size;
    u8  mode;

    u8  service_code_list[2] = {0x0B, 0x10};
    u8  block_list[2] = {0x80, 0x00};
    u8  block_size;
    u8  block_data[16];
    u8  status_flag[2];
    u8  write_data[16] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00};
    u8  syscode_size;
    u8  syscode_list[2];

    g_statistics.felica_cnt++;
    g_statistic_refreshed = TRUE;

    status = pcd_request_c(&pcmd[4], pcmd[6], pcmd[7], pcmd[1], rsp);

    if(status != MI_OK)
    {
        err = com_status_check(status);
        make_packet(COM_PKT_CMD_ERR_STA_STATISTICS, (u8*)&(err), sizeof(err));

        g_statistics.felica_fail++;
        if(NFC_DEBUG_LOG)
        {
            printf("reqc_fail:%d\n", (u16)status);
        }


    }
    else
    {
        make_packet(COM_PKT_CMD_CARD_TYPE, rsp, 18);

        /* In theory this condition can never be met */
        if(status == MI_NY_IMPLEMENTED)
        {
            status = pcd_req_resp(&rsp[2], &mode);      //felica请求响应
            if(status == MI_OK)
            {
                status = pcd_req_service(&rsp[2], 1, node_code_list, &node_size, node_key_version_list);        //felica请求服务

                if(status == MI_OK)
                {
                    pcd_read_without_encryption(&rsp[2], 1, service_code_list, 1, block_list, sizeof(block_list), &block_size, block_data, status_flag);
                    if(status == MI_OK)
                    {
                        if(NFC_DEBUG_LOG)
                        {
                            printf("status_flag: %02x", (u16)status_flag[0]);
                            printf(" %02x\n", (u16)status_flag[1]);
                        }


                        pcd_write_without_encryption(&rsp[2], 1, service_code_list, 1, block_list, sizeof(block_list), write_data, status_flag);
                        if(status == MI_OK)
                        {
                            if(NFC_DEBUG_LOG)
                            {
                                printf("status_flag: %02x", (u16)status_flag[0]);
                                printf(" %02x\n", (u16)status_flag[1]);
                            }


                            pcd_req_syscode(&rsp[2], &syscode_size, syscode_list);
                            if(status == MI_OK)
                            {
                                if(NFC_DEBUG_LOG)
                                {
                                    printf("sys code: %02x", (u16)syscode_list[0]);
                                    printf(" %02x\n", (u16)syscode_list[1]);
                                }

                            }
                        }


                    }
                }
            }
        }
    }
    return status;
}

int com_inventory(u8 *pcmd)
{
    int status;

    u8  maskval[8];
    u8  masklen = 0;
    u8  err;
    u8  i, j;
    u8 card_num = 0;

    if(pcmd[4] == TRUE)
    {
        do {
            status = pcd_inventory(pcmd[1], pcmd[3], maskval, masklen, &bTypeV_Info_t);
            if(status != MI_OK)
            {

            }
            else
            {
                if(NFC_DEBUG_LOG)
                {
                    printf("ISO15693--UID:\n");
                }


                for(j = 0; j < bTypeV_Info_t.bCardNum; j++)
                {
                    for(i = 0; i < 7; i ++)
                    {
                        printf("%02X ", (u16)bTypeV_Info_t.aTypeV[j].aUid[i]);
                    }
                    printf("%02X\n", (u16)bTypeV_Info_t.aTypeV[j].aUid[i]);
                }
                for(j = 0; j < bTypeV_Info_t.bCardNum; j++)
                {
                    status = pcd_stay_quiet(bTypeV_Info_t.aTypeV[j].aUid, 0x22);
                    card_num++;
                }
            }

        } while(status == MI_OK);
        memcpy(iso15693_uid, bTypeV_Info_t.aTypeV[0].aUid, ISO15693_UID_LENGTH);
        if(NFC_DEBUG_LOG)
        {
            printf("card num = %02d\n\n", (u16)card_num);
        }

    }
    else
    {
        g_statistics.inv_cnt++;
        g_statistic_refreshed = TRUE;

        status = pcd_inventory(pcmd[1], pcmd[3], maskval, masklen, &bTypeV_Info_t);

        if(status != MI_OK)
        {
            err = com_status_check(status);
            make_packet(COM_PKT_CMD_ERR_STA_STATISTICS, (u8*)&(err), sizeof(err));

            g_statistics.inv_fail++;
            if(NFC_DEBUG_LOG)
            {
                printf("reqv_fail:%d\n", (u16)status);
            }

        }
        else
        {
            make_packet(COM_PKT_CMD_ISO15693_INVENTORY, bTypeV_Info_t.aTypeV[0].aUid, ISO15693_UID_LENGTH);

            if(NFC_DEBUG_LOG)
            {
                printf("ISO15693--UID:\n");
                for(i = 0; i < 7; i ++)
                {
                    printf("%02X ", (u16)bTypeV_Info_t.aTypeV[0].aUid[i]);
                }
                printf("%02X\n", (u16)bTypeV_Info_t.aTypeV[0].aUid[i]);

            }

            memcpy(iso15693_uid, &bTypeV_Info_t.aTypeV[0].aUid, ISO15693_UID_LENGTH);
        }
    }


    return status;
}


int com_typeb_attrib(void)
{
    int status;

    status = pcd_attri_b(&prama_ATQB[1], 0, prama_ATQB[10]&0x0f, PICC_CID, prama_ATQB);
    return status;

}

void com_stay_quiet(u8 *pcmd)
{
    pcd_stay_quiet(iso15693_uid, pcmd[1]);
}

void com_reset_to_ready(u8 *pcmd)
{
    pcd_reset_to_ready(iso15693_uid, pcmd[1]);
}

void com_select(u8 *pcmd)
{
    u8 err = 0;

    pcd_select(iso15693_uid, pcmd[1], &err);
    if(err != 0)
    {
        if(NFC_DEBUG_LOG)
        {
            printf("ErrCode = %02x\n", (u16)err);
        }

    }
}
void com_get_sys_info(u8 *pcmd)
{
    u8 err = 0;
    u8 resbuff[15];
    u16 bufflen;
    int status = MI_OK;

    status = pcd_get_system_information(iso15693_uid, pcmd[1], &err, resbuff, &bufflen);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
        make_packet(COM_PKT_CMD_ISO15693_GET_SYSTEM, resbuff, bufflen);

    }
}
void com_get_block_status(u8 *pcmd)
{
    u8 i;
    u8 err = 0;
    u8 block_status[12];
    u16 block_status_length;
    int status = MI_OK;

    status = pcd_get_multiple_block_security_status(iso15693_uid, pcmd[1], pcmd[2], pcmd[3], &err, block_status, &block_status_length);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
        if(NFC_DEBUG_LOG)
        {
            printf("block_status: ");
            for(i = 0; i < block_status_length; i++)
            {
                printf(" %02x", block_status[block_status_length]);
            }
            printf("\n");
        }

    }
}

void com_read_single_block(u8 *pcmd)
{
    u8 err = 0;
    u8 block_data[5];
    u16 data_length;
    int status = MI_OK;

    status = pcd_read_single_block(iso15693_uid, pcmd[1], pcmd[2], block_data, &err, &data_length);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
        if(pcmd[1] & BIT6)
        {
            make_packet(COM_PKT_CMD_ISO15693_READ_SINGLE, &block_data[1], data_length - 1);
        }
        else
        {
            make_packet(COM_PKT_CMD_ISO15693_READ_SINGLE, block_data, data_length);
        }
    }

}

void com_write_single_block(u8 *pcmd)
{
    u8 err = 0;
    u16 data_length = 4;
    int status = MI_OK;
    u8 recvbuff[2];
    u16 recvlen;

    status = pcd_write_single_block(iso15693_uid, pcmd[1], pcmd[2], &pcmd[3], &err, data_length);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
    else if((pcmd[1] & OPTION_FLAG) && (status == MI_NOTAGERR))
    {
        status = pcd_send_eof(recvbuff, &recvlen);
    }
}

void com_lock_block(u8 *pcmd)
{
    u8 err = 0;
    int status = MI_OK;

    status = pcd_lock_block(iso15693_uid, pcmd[1], pcmd[2], &err);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_read_multiple_block(u8 *pcmd)
{
    u8 err = 0;
    u8  databuff[40];
    u16 datalen;
    int status = MI_OK;

    status = pcd_read_multiple_block(iso15693_uid, pcmd[1], pcmd[2], pcmd[3], databuff, &err, &datalen);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_write_multiple_block(u8 *pcmd)
{
    u8 err = 0;
    u8  databuff[40] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C};
    u16 datalen = 12;
    int status = MI_OK;

    status = pcd_write_multiple_block(iso15693_uid, pcmd[1], pcmd[2], pcmd[3], databuff, &err, datalen);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_write_afi(u8 * pcmd)
{
    u8 err = 0;
    int status = MI_OK;

    status = pcd_write_afi(iso15693_uid, pcmd[1], pcmd[2], &err);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_lock_afi(u8 *pcmd)
{
    u8 err = 0;
    int status = MI_OK;

    status = pcd_lock_afi(iso15693_uid, pcmd[1], &err);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_write_dsfid(u8 * pcmd)
{
    u8 err = 0;
    int status = MI_OK;

    status = pcd_write_dsfid(iso15693_uid, pcmd[1], pcmd[2], &err);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_lock_dsfid(u8 *pcmd)
{
    u8 err = 0;
    int status = MI_OK;

    status = pcd_lock_dsfid(iso15693_uid, pcmd[1], &err);

    if(status == MI_OK)
    {
        if(err != 0)
        {
            if(NFC_DEBUG_LOG)
            {
                printf("ErrCode = %02x\n", (u16)err);
            }

            return;
        }
    }
}

void com_transfer(u8* pcmd)
{
    int  status = MI_OK;
    hal_nfc_transceive_t pi;

    printf("com_transfer:\n");

    hal_nfc_write_register(0x2b, (4095) & 0xFF);
    hal_nfc_write_register(0x2a, BIT7 | (((4095)>>8) & 0xFF));

    hal_nfc_write_register(0x2d, 0x682  & 0xFF);
    hal_nfc_write_register(0x2c, (0x682 & 0xFF00) >> 8);

    pi.mf_command = PCD_TRANSCEIVE;
    pi.mf_length = pcmd[1];
    memcpy(pi.mf_data, &pcmd[2], pi.mf_length);
    status = pcd_com_transceive(&pi);
    printf("status:%d\r\n",status);

}

U32 bigToLittle(U32 value)
{
    U32 temp = 0;

    *((U8*)&temp+0) = *((U8*)&value+3);
    *((U8*)&temp+1) = *((U8*)&value+2);
    *((U8*)&temp+2) = *( (U8*)&value+1);
    *((U8*)&temp+3) = *((U8*)&value+0);
    return temp;
}

uint8_t g_execute_once = FALSE; //自动执行
uint8_t g_query_mode = 0; //手动操作芯片模式
uint8_t g_typa_poll = 1;
uint8_t g_typb_poll = 1;
uint8_t g_need_reconfig = FALSE;//需要重新初始化PCD的协议类
uint32_t g_polling_cnt = 0;
uint8_t g_lpcd_config_test_start = TRUE;//LPCD周期自动探测卡功能是否开
u8 mifare_poll = FALSE;
u8 mifare_rpolling = FALSE;
u8 mifare_wpolling = FALSE;

u8 g_polling_param[32];

void rfid_cmd_process(void *pkt)
{
    pc_tx_pkt *ppkt = (pc_tx_pkt *)pkt;
    switch(ppkt->cmd)
    {
    case COM_PKT_CMD_READ_REG:
    {   
        reg_pkt_s reg_pkt;
        uint8_t   reg[2];
        reg_pkt.addr=ppkt->datu.reg.addr;   //get addr
        reg_pkt.page=ppkt->datu.reg.rw_dat; //get page

        reg[0]=reg_pkt.addr;    //the upper tester still use two bytes of prama.

        reg_pkt.reg_value = hal_nfc_get_register(reg_pkt.page,reg_pkt.addr,1);
        reg[1]=reg_pkt.reg_value;

        make_packet(COM_PKT_CMD_READ_REG, (u8 *)&reg, sizeof(reg));
        break;
    }

    case COM_PKT_CMD_WRITE_REG:
    {
        unsigned char* regpkt= (void*)pkt;
        reg_pkt_s reg_pkt;
        reg_pkt.addr = (uint8_t)regpkt[3];   
        reg_pkt.reg_value = (uint8_t)regpkt[4];            
        reg_pkt.page = (uint8_t)regpkt[5];  
        hal_nfc_set_register(reg_pkt.page,reg_pkt.addr,reg_pkt.reg_value,1);

        break;
    }
    case COM_PKT_CMD_REQ_SELECT:
    {
        g_execute_once = TRUE;


        break;
    }

    case COM_PKT_CMD_LOAD_PASSWORD_A:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        memcpy(g_tag_info.uncoded_key, ppkt->datu.dat + 1, 6);
        g_tag_info.uncoded_key_is_a = TRUE;
        break;
    }
    case COM_PKT_CMD_LOAD_PASSWORD_B:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        memcpy(g_tag_info.uncoded_key, ppkt->datu.dat + 1, 6);
        g_tag_info.uncoded_key_is_a = FALSE;
        break;
    }
    case COM_PKT_CMD_READ_CARD:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];

        break;
    }
    case COM_PKT_CMD_WRITE_CARD:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        memcpy(g_tag_info.block.block_data, ppkt->datu.dat + 1, 16);
        break;
    }
    case COM_PKT_CMD_INIT_BLOCK:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        break;
    }
    case COM_PKT_CMD_PLUS_ONE_BLOCK:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        break;
    }
    case COM_PKT_CMD_DECREASE_ONE_BLOCK:
    {
        g_execute_once = TRUE;

        g_tag_info.block.num = ppkt->datu.dat[0];
        break;
    }
    case COM_PKT_CMD_SWITCH_SPI:
    {

        break;
    }
    case COM_PKT_CMD_QUERY_MODE:
    {
        if (ppkt->datu.dat[0] == 1)
        {
            g_query_mode = TRUE;
            if (ppkt->datu.dat[1] == 1)
            {   //typeA poll
                //                  hal_nfc_config(COS_typeA_configs, sizeof(COS_typeA_configs)/sizeof(hal_nfc_regval_t));
                g_typa_poll = TRUE;
            }
            else
            {
                g_typa_poll = FALSE;
            }
            if (ppkt->datu.dat[2] == 1)
            {   //typeB poll
                //                  hal_nfc_config(COS_typeB_configs, sizeof(COS_typeB_configs)/sizeof(hal_nfc_regval_t));
                g_typb_poll = TRUE;
            }
            else
            {
                g_typb_poll = FALSE;
            }
            if (g_typa_poll && g_typb_poll)
            {
                g_need_reconfig = TRUE;
            }
            else
            {
                g_need_reconfig = FALSE;
            }
            g_polling_cnt = *((u32*)&ppkt->datu.dat[3]);
            g_polling_cnt = bigToLittle(g_polling_cnt);
            printf("g_polling_cnt=%d\n", g_polling_cnt);
        }
        else
        {
            g_query_mode = FALSE;
        }
        break;
    }
    case COM_PKT_CMD_TYPEC_FELICA_POLLING:
    {
        if(ppkt->datu.dat[0] == 0x01)
        {
            printf("212k\n");
            pcd_set_rate('2', 'F');
        }
        else if(ppkt->datu.dat[0] == 0x02)
        {
            printf("424k\n");
            pcd_set_rate('4', 'F');
        }
        g_query_mode_felica = ppkt->datu.dat[11];
        memcpy(&g_polling_param, &ppkt->cmd, 8);
        g_polling_cnt = (ppkt->datu.dat[7]<<24) + (ppkt->datu.dat[8]<<16) + (ppkt->datu.dat[9]<<8) + ppkt->datu.dat[10];
    }
    break;
    case COM_PKT_CMD_ISO15693_POLLING:
    {
        g_15693_polling_conf.blocknum=ppkt->datu.dat[9];
        g_15693_polling_conf.blocksize=ppkt->datu.dat[10];
        g_15693_polling_conf.flag=ppkt->datu.dat[5];
        g_query_mode_iso15693 = ppkt->datu.dat[0]; //data0= 01
        memcpy(g_polling_param, &ppkt->datu.dat[4], 4); //data4=40
        g_polling_cnt = (ppkt->datu.dat[1]<<24) + (ppkt->datu.dat[2]<<16) + (ppkt->datu.dat[3]<<8) + ppkt->datu.dat[4];
    }
    break;
    case COM_PKT_CMD_CHIP_RESET:
    {
        hal_nfc_pcd_reset();
        printf("PCD reset\r\n");
        break;
    }
    case COM_PKT_CMD_HALT:
    {
        pcd_hlta();
        printf("HltA\n");
        break;
    }

    case COM_PKT_CMD_LPCD_CONFIG_TEST:
    {
        g_lpcd_config.delta = ppkt->datu.dat[0];
        memcpy(&g_lpcd_config.t_inactivity_ms, &ppkt->datu.dat[1], 4);
        g_lpcd_config.skip_times = (u32)ppkt->datu.dat[5];
        g_lpcd_config.skip_cnt  = (u32)ppkt->datu.dat[6];// skip_cnt
        g_lpcd_config.t_detect_us = (u32)ppkt->datu.dat[7];
        g_lpcd_config.detect_way = (u32)ppkt->datu.dat[8];
        g_lpcd_config.t_inactivity_ms = ntohl(g_lpcd_config.t_inactivity_ms);
        pcd_lpcd_config_start(g_lpcd_config);
        printf("config=%d,%lu,%d,%d\n",g_lpcd_config.delta, g_lpcd_config.t_inactivity_ms, g_lpcd_config.skip_times, g_lpcd_config.t_detect_us);
        g_lpcd_config_test_start = TRUE;
        break;
    }
    case COM_PKT_CMD_LPCD_CONFIG_TEST_STOP:
    {
        pcd_lpcd_end();
        g_lpcd_config_test_start = FALSE;
        break;
    }
    case COM_PKT_CMD_MIFARE_RWPOLLING:
    {
        if (ppkt->datu.dat[0] == 1)
        {
            mifare_poll = TRUE;
            if (ppkt->datu.dat[1] == 1)
            {
                mifare_rpolling = TRUE;
                mifare_wpolling = FALSE;
                memcpy(g_polling_param, &ppkt->datu.dat[5], 9);
            }
            else
            {
                mifare_wpolling = TRUE;
                mifare_rpolling = FALSE;
                memcpy(g_polling_param, &ppkt->datu.dat[5], 25);
            }
            g_polling_cnt = (ppkt->datu.dat[2]<<24) + (ppkt->datu.dat[3]<<16) + (ppkt->datu.dat[4]<<8) + ppkt->datu.dat[5];
            printf("g_polling_cnt=%lu\n", g_polling_cnt);
        }
        else
        {
            mifare_poll = FALSE;
        }
        break;
    }
    case COM_PKT_CMD_AUTO_READ_TYPEB_ID:
    {
        if (ppkt->datu.dat[0] == 1)
        {
            g_auto_read_typeB_id = 1;
        }
        else//ppkt->datu.dat[0] ==false
        {
            g_auto_read_typeB_id = 0;
        }
        break;
    }
    case COM_PKT_CMD_AUTO_READ_WRITE:
    {
        if (ppkt->datu.dat[0] == 1)
        {
            g_auto_read_write = 1;
        }
        else
        {
            g_auto_read_write = 0;
        }
        break;
    }
    case COM_PKT_CMD_SOC2014_FIX:
    {

        break;
    }
    case COM_PKT_CMD_POWERON:
    {
        drv_interface.hw_set_pcd_power(1);
        break;
    }
    case COM_PKT_CMD_POWERDOWN:
    {
        drv_interface.hw_set_pcd_power(0);
        break;
    }
    default:
        card_operation(&ppkt->cmd);
        break;
    }
}

//void apdu_exchange(u8 * pcmd)
//{
//    u8  loop_buf[256];
//    char  status;
//
//    u16  tx_len;
//    unsigned int rx_len;
//
//    g_statistics.cosa_cnt++;  //mark
//    g_statistics.cosb_cnt++;
//
//    tx_len = pcmd[1];
//    memcpy(loop_buf, pcmd + 2, tx_len);
//    dk_log_hex("loop_buf", loop_buf, tx_len+1);
//    status = ISO14443_4_HalfDuplexExchange(&g_pcd_module_info, loop_buf, tx_len, loop_buf, &rx_len);
//
//    if (status == MI_OK && rx_len < sizeof(loop_buf))
//    {
//        memmove(loop_buf+1, loop_buf, rx_len);
//        loop_buf[0]=rx_len;
//        dk_log_hex("rcv", loop_buf+1, loop_buf[0]);
//       // make_packet(COM_PKT_CMD_EXCHANGE, (u8*)&loop_buf, rx_len + 1);
//    }
//    if (status != MI_OK)
//    {
//        g_statistics.cosa_fail++; //mark
//        g_statistics.cosb_fail++;
//    }
//
//
//    g_statistic_refreshed = TRUE;
//
//
//}

volatile PDU_STATUS_DEF gt_pdu_status = {0, 0, 0, T1_FRAME_B, 0};


/*******************************************************************************
 *  函数名：   pollingA()
 *  功能：    读A卡
 *  入口参数：ats-存放返回ATS，首字节表示ATS长度
 *  返回参数：0-没有寻到卡片（或激活卡片失败），1-A卡，2-B卡，3-Felica,4-MF卡
 *  作者：    Awen
 *******************************************************************************/
uint8_t pollingA(uint8_t *ats, uint8_t *len, uint8_t *card_type, uint8_t protocolLayer) {
    int32_t status;
    uint8_t tag_type_bytes[2];
    uint8_t sak;
    uint8_t *serial_num = ats;
    uint8_t uid_len = 0;

    pcd_default_info();

    status = pcd_request(PICC_REQALL, tag_type_bytes);
    //一次防冲突及选卡
    if ((status == MI_OK) || (status == MI_COLLERR)) {
        uid_len = UID_4;
        status = pcd_cascaded_anticoll(PICC_ANTICOLL1, 0, &serial_num[0]);
        if (status != MI_OK) {
            return false;
        }
        status = pcd_cascaded_select(PICC_ANTICOLL1, &serial_num[0], &sak);
        if (status != MI_OK) {
            return false;
        }
    }
    else {
        return false;
    }

    //二次防冲突及选卡
    if((status == MI_OK) && (sak & BIT2)) {
        uid_len = UID_7;
        status = pcd_cascaded_anticoll(PICC_ANTICOLL2, 0, &serial_num[4]);
        if(status != MI_OK) {
            return false;
        }
        status = pcd_cascaded_select(PICC_ANTICOLL2, &serial_num[4], &sak);
        if(status != MI_OK) {
            return false;
        }
    }

    if (protocolLayer == ISO14443_P3) {
        gt_pdu_status.protocolLayer = ISO14443_P3;
        if ((sak & 0x28) == 0) {
            *card_type = RF_TYPE_UL;
            ats[7] = sak;
            (*len) = uid_len + 1;
        }
        else {
            *card_type = RF_TYPE_MF;
            ats[4] = sak;
            (*len) = uid_len + 1;
        }
        return true;
    }

    //检测卡片协议类型
    dk_log_ln("sak=%02x", sak);
    if ( (sak & 0x20) != 0 ) {  //SCK的bit6判断PICC是否遵循ISO1443-P4为1则支持
        gt_pdu_status.protocolLayer = ISO14443_P4;
    }
    else {
        gt_pdu_status.protocolLayer = ISO14443_P3;
        if ((sak & 0x08) == 0) {
            *card_type = RF_TYPE_UL;
            ats[7] = sak;
            (*len) = uid_len + 1;
        }
        else {
            *card_type = RF_TYPE_MF;
            ats[4] = sak;
            (*len) = uid_len + 1;
        }
        return true;
    }

    uint8_t CID = 0;
    uint8_t *p_ats = ats + uid_len;
    status = pcd_rats_a(CID, p_ats);
    if(status != MI_OK) {
        return false;
    }

    hal_nfc_transceive_t pi;
    status = pcd_pps_rate(&pi, p_ats, CID, 1);
    if(status != MI_OK) {
        return false;
    }
    *len = uid_len;
    if (uid_len == 4) {
        *card_type = ISO14443_A;
    }
    else if (uid_len == 7){
        *card_type = RF_TYPE_DF;
    }
    (*len) += p_ats[0];
    return true;
}

/*******************************************************************************
 *  函数名：  PcdAntennaOn()
 *  功能：    打开天线
 *  入口参数：void
 *  返回参数：void
 *  作者：    Lochy
 *******************************************************************************/
void PcdAntennaOn(void) {
    hal_nfc_antenna_on();
    sys_delay_ms(5);
}

/*******************************************************************************
 *  函数名：  PcdAntennaOff()
 *  功能：    关闭天线
 *  入口参数：void
 *  返回参数：void
 *  作者：    Lochy
 *******************************************************************************/
void PcdAntennaOff(void) {
    hal_nfc_antenna_off();
    hal_nfc_reinit();

}

int CardCpu_authentication(uint8_t *rx_data)
{
    uint8_t status,i;
    uint8_t rx_buf[256];
    unsigned int rx_len;

    uint8_t Car_key[5]={0x00,0x84,0x00,0x00,0x08}; //get 8-byte random number
    uint8_t Ex_Key0[5]={0x00,0x82,0x00,0x00,0x08}; //The default card external authentication command


    uint8_t APDU1[]={0x00,0xA4,0x04,0x00,0x10,0xD1,0x56,0x00,0x01,0x01,0x00,0x01,0x60,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00}; //An external authentication command with key identification number 1
    uint8_t APDU2[]={0x80,0xCA,0x00,0x44,0x00}; //An external authentication command with key identification number 2
    uint8_t Plaintext[8];//DES Plaintext
    uint8_t Ciphetext[8];//DE ciphertext
    uint8_t Ex_key[13];//External AUTHENTICION
    uint8_t ats[256];
    uint8_t send_temp[] = {0x00, 0x36, 0x00, 0x00, 0x08};
    uint8_t *pRead;
    uint16_t readLen = 0;
    uint8_t ats_len;

    uint8_t pcmd[] = {0x00, 21,0x00,0xA4,0x04,0x00,0x10,0xD1,0x56,0x00,0x01,0x01,0x00,0x01,0x60,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00};

    PRINT("CardCpu_authentication\n");

    PcdAntennaOff();
    sys_delay_ms(10);
    PcdAntennaOn();

    hal_nfc_config(COS_typeA_configs, sizeof(COS_typeA_configs)/sizeof(hal_nfc_regval_t));

    int sta = pollingA(&ats[1], &ats_len, &ats[0], ISO14443_P4);

    if ( sta != true ) {
        return MI_AUTHERR;
    }
    //      sys_delay_ms(200);
    //      free_dog();
    //      sys_delay_ms(200);
    //       free_dog();

    // g_pcd_module_info.ui_fwi = 8;

    status = ISO14443_4_HalfDuplexExchange(&g_pcd_module_info, APDU1, sizeof(APDU1), rx_buf, &rx_len);  //ܱȡ̦ܺ˽

    if (status == HAL_STATUS_OK)
    {
        dk_log_hex("APDU 1 : ", rx_buf,rx_len);  //
        if(rx_buf[rx_len - 2] == 0x90 && rx_buf[rx_len - 1] == 0x00){
            status = ISO14443_4_HalfDuplexExchange(&g_pcd_module_info, APDU2, sizeof(APDU2), rx_buf, &rx_len);  //ܱȡ̦ܺ˽
            dk_log_hex("APDU 2 : ", rx_buf,rx_len);  //
            if(rx_buf[rx_len - 2] == 0x90 && rx_buf[rx_len - 1] == 0x00){
                memcpy(rx_data, rx_buf, rx_len - 2);
                return MI_OK;
            }
        }
        else{
            return MI_AUTHERR;
        }
    }
    return MI_AUTHERR;
}
unsigned char  pps_pcmd = 0;

void g_lpcd_init(void){
    // 07 00 00 00 64 06 00 06 02 04
    uint8_t dat[] = {0x07, 0x00, 0x00, 0x00, 0x64, 0x06, 0x00, 0x06, 0x02, 0x04};
    g_lpcd_config.delta = dat[0];
    memcpy(&g_lpcd_config.t_inactivity_ms, &dat[1], 4);
    g_lpcd_config.skip_times = (u32)dat[5];
    g_lpcd_config.skip_cnt  = (u32)dat[6];// skip_cnt
    g_lpcd_config.t_detect_us = (u32)dat[7];
    g_lpcd_config.detect_way = (u32)dat[8];
    g_lpcd_config.t_inactivity_ms = ntohl(g_lpcd_config.t_inactivity_ms);
    pcd_lpcd_config_start(g_lpcd_config);
    printf("config=%d,%lu,%d,%d\n",g_lpcd_config.delta, g_lpcd_config.t_inactivity_ms, g_lpcd_config.skip_times, g_lpcd_config.t_detect_us);
    g_lpcd_config_test_start = TRUE;
}

static int cmcc_card_read(uint8_t *SEID, uint8_t *len){
    int err = MI_AUTHERR;

    uint8_t pcmd[] = {0x01, 0x00,  0x33, 0xBA, 0x4E,0x46};
    uint8_t rxData[256] = {0};

    if(!gt_sys_val.u32sys_flag.b1_nfc_data_delay_auth_flag){
        return MI_AUTHERR;
    }
    pcd_default_info();
    // com_typea_rats(pcmd); // RATS
    err = CardCpu_authentication(rxData);

    if(err == MI_OK){
        SeidRespApduDef *SeidRespApduPtr = (SeidRespApduDef *)rxData;
        if(SeidRespApduPtr->head[0] == 0x00 && SeidRespApduPtr->head[1] == 0x44){
            memcpy(SEID, SeidRespApduPtr->seidData, SeidRespApduPtr->seidLen);
            *len = SeidRespApduPtr->seidLen;
        }
        else{
            err = MI_AUTHERR;
        }
    }

    return err;
}

void rfid_task(void)
{
    uint32_t g_statistic_last_t = 0;
    uint8_t SEID[64] = {0};
    uint8_t len = 0;
    static uint32_t last_tick = 0;
    uint8_t serial_num[10] = {0};
    uint8_t card_auth_restul = CARD_AUTH_FAIL;
    uint8_t test_is_super_card_flag = 0;

    static uint32_t cnt = 0;
//    if(cnt++ % 50000 == 0){
//        printf("work_mode:%d\r\n", work_mode);
//    }

    //    //自动卡检测参数测试
    if ( work_mode == MODE_PCD_ONLY)
    {
        u8 status;
        if(g_lpcd_config.detect_way == 2)
        {   //interrupt
            if ((g_lpcd_config.card_to_enter == FALSE) && (TRUE == pcd_lpcd_check()))
            {
                u8 tag_type[2] = {0};

                g_statistics.lpcd_cnt++;
                g_statistic_refreshed = TRUE;
                statistic_print();

                if(!gt_sys_val.u32sys_flag.b1_nfc_data_delay_auth_flag){
                    return;
                }

                while(BLK_Task_is_Busy(BLK_TASK_ADC | BLK_TASK_TOUCH));
                BLK_Task_Set(BLK_TASK_NFC);
                TKY_SaveAndStop();    //---对相关寄存器进行保存---

                //验证是否有卡入场
                hal_nfc_config(COS_typeA_configs, sizeof(COS_typeA_configs)/sizeof(hal_nfc_regval_t));
                status = pcd_request(0x52, tag_type);
                //刚检测到卡时可能处于距离边缘，有可能第一次寻卡失败，所以增加第二次寻卡验证
                if (status != MI_OK)
                {
                    status = pcd_request(0x52, tag_type);
                }
                ///刚检测到卡时可能处于距离边缘，如果前两次寻卡失败，则第三次寻卡验证
                if (status != MI_OK)
                {
                    status = pcd_request(0x52, tag_type);
                }

                if (status == MI_OK)
                {   //有卡片入场
                    printf("card to enter2\n");
                    dk_log_hex("tag_type", tag_type, 2);
                    uint8_t ats[32];
                    uint8_t ats_len;
                    uint8_t cardType;
                    uint8_t poll_status;
                    uint8_t sak;
//                    poll_status = pollingA(ats, &ats_len, &cardType, ISO14443_P4);
//                    printf("poll_status:%d\n", poll_status);
//                    读取SEID成功
//                    if(poll_status == true && cardType == ISO14443_A && cmcc_card_read(SEID, &len) == MI_OK){
//                        dk_log_hex("seid", SEID, len);
//                        card_process_main_loop(SEID);
//                        TKY_LoadAndRun();
//                        BLK_Task_Clear(BLK_TASK_NFC);
//                        //等待卡离场，应用代码中可不必等待离场
//                        g_lpcd_config.card_to_enter = TRUE;
//                        pcd_lpcd_config_start(g_lpcd_config);
//                    }
                    //证明读到卡
                   // else
                        if( /*tag_type != 0 && */MI_OK == pcd_cascaded_anticoll(PICC_ANTICOLL1, 0, &serial_num[0])){
                        dk_log_hex("uid", serial_num, 10);

                        status = pcd_cascaded_select(PICC_ANTICOLL1, &serial_num[0], &sak);
                        if (status == MI_OK) {
                            if((sak & 0x20) != 0 && cmcc_card_read(SEID, &len) == MI_OK){
                                memcpy(serial_num, SEID, 10);
                                test_is_super_card_flag = 1;
                            }
                        }
                        if(test_is_super_card_flag){
                            card_auth_restul = CARD_AUTH_OK;
                            set_is_super_sim_card_open();
                            lock_ctrl_open_close(LOCK_OEPN_TIME*1000/0.625);
                        }
                        else{
                            card_auth_restul = card_process_main_loop(serial_num);
                        }
                        if(card_auth_restul == CARD_AUTH_OK){
                            TKY_LoadAndRun();
                            BLK_Task_Clear(BLK_TASK_NFC);
                            //等待卡离场，应用代码中可不必等待离场
                            g_lpcd_config.card_to_enter = TRUE;
                            pcd_lpcd_config_start(g_lpcd_config);
                        }
                    }
                   // if(0){}
                    //初始化为标签模式
                    if(card_auth_restul != CARD_AUTH_OK)
                    {
                        hal_nfc_reinit();
                        picc_init();
                        last_tick = drv_interface.hw_get_tick();
                        work_mode = MODE_PICC_ONLY;
                        printf("picc enter1\n");
                    }
                }
                else
                {
                    hal_nfc_reinit();
                    picc_init();
                    last_tick = drv_interface.hw_get_tick();
                    work_mode = MODE_PICC_ONLY;
                    printf("picc enter2\n");
                    //                    g_statistics.lpcd_fail++;
                    //                    g_statistic_refreshed = TRUE;
                    //                    pcd_lpcd_config_start(g_lpcd_config);
                }
                gt_sys_val.u32sys_flag.b1_is_nfc_finish_flag = false;
            }
            if((g_lpcd_config.card_to_enter == TRUE) && (TRUE == pcd_lpcd_check()))
            {
                printf("card to leave\n");
                TKY_LoadAndRun();
                BLK_Task_Clear(BLK_TASK_NFC);
                g_lpcd_config.card_to_enter = FALSE;
                pcd_lpcd_config_start(g_lpcd_config);
            }
        }
    }
    else{
        if(!drv_interface.hw_is_timeout(last_tick, MS1_TO_SYSTEM_TIME(5000))){
            picc_event_process();
        }
        else{
            printf("picc exit\n");

            work_mode = MODE_PCD_ONLY;
            g_statistic_refreshed = TRUE;
            TKY_LoadAndRun();
            BLK_Task_Clear(BLK_TASK_NFC);
            //等待卡离场，应用代码中可不必等待离场
            g_lpcd_config.card_to_enter = FALSE;
            pcd_lpcd_config_start(g_lpcd_config);
        }
    }

}

void pcd_lpcd_config_start(lpcd_config_t lpcd_config)
{
    u8 WUPeriod;
    u8 SwingsCnt;
    u8 versions;

    gt_sys_val.u32sys_flag.b1_is_nfc_finish_flag  = true;

    versions = hal_nfc_get_register(3,0x37,1);
    //if(NFC_DEBUG_LOG)
    {
        printf("pcd_lpcd_config_start\n");
    }
    WUPeriod  = lpcd_config.t_inactivity_ms*32.768/256+0.5;
    SwingsCnt = lpcd_config.t_detect_us*27.12/2/16 + 0.5;
    hal_nfc_pcd_reset();//先复位寄存器再进行lpcd
    hal_nfc_set_register(1,0x14,0xCB,1);//Tx2CW=1 ,contiune 载波打开
    hal_nfc_set_register(3,0x37,0x00,1);//恢复版本号
    hal_nfc_set_register(4,0x3C,(0X30|lpcd_config.delta),1); //设置Delta[3:0]的值, 开启32k
    hal_nfc_set_register(4,0x3D,WUPeriod,1);     //设置休眠时间
    hal_nfc_set_register(4,0x3E,0X80 | ((lpcd_config.skip_cnt & 0x07) << 4) | (SwingsCnt & 0x0F),1);   //开启LPCD_en设置,跳过探测次数，探测时间
    hal_nfc_set_register(3,0x37,0x00,1); //关闭私有寄存器保护开关
    if(versions ==0x19)
    {
        hal_nfc_set_register(6,0x33,0x20,1);
        hal_nfc_set_register(6,0x39,0x20,1); //新增
        hal_nfc_set_register(6,0x3b,0x80|lpcd_config.skip_times,1);
        hal_nfc_set_register(6,0x36,0x80,1);


    }
    hal_nfc_set_register(0,0x03,0xA0,1);   //打开卡探测中断使能
    hal_nfc_set_register(0,0x01,0x10,1);   //PCD soft powerdown

    hal_nfc_clear_register_bit(0x02,BIT7);   //具体应用相关，配置为高电平为有中断

}




void pcd_lpcd_end(void)
{
    if(NFC_DEBUG_LOG)
    {
        printf("pcd_lpcd_end\n");
    }
    hal_nfc_pcd_reset();//复位



}



u8 pcd_lpcd_check(void)
{
    // PRINT("<-lpcdC\n");
    if(INT_PIN&& (hal_nfc_read_register(REG_DIVIRQ) & BIT5)) //TagDetIrq
    {
        hal_nfc_write_register(REG_DIVIRQ,BIT5);     //清除卡检测到中断
        pcd_lpcd_end();
        PRINT("<-lpcdC:Irq\n");

        return 1;
    }
    return 0;

}




